package com.example.tccdemo.task;

import com.example.tccdemo.db163.dao.PaymentMsgMapper;
import com.example.tccdemo.db163.model.PaymentMsg;
import com.example.tccdemo.db163.model.PaymentMsgExample;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author caryguan
 * @version V1.0
 * @Package com.example.tccdemo.task
 * @date 2020/10/15 22:40
 */

@Service
public class OrderScheduler {

    @Resource
    private PaymentMsgMapper paymentMsgMapper;

    //把所有状态为未发送的消息表数据取出来

    @Scheduled(cron = "0/10 * * * * ?")
    public void orderNotify() throws IOException {
        //基于本地消息表的分布式事务的处理方案实现
        //分三步:1把和当前业务逻辑以外的这些事务消息放在一张消息表中,比如paymentMsg和account表解耦,这两个表在同一个数据库
        //2.提供一个分布式事务的调用接口,通过本地消息表调用httpClient去访问这个接口,更改另一张表内的订单状态
        //3.通过定时任务的方式去调用这个接口,如果成功后返回success,失败返回failure,然后在通过这个状态码去修改消息表的状态,
        //如果超过了最大重试次数,消息表修改状态,人工介入,其实就类似于对接支付宝和微信,支付消息在他那里,我们应用提供一个回调接口
        //ali或者腾讯调用我们的回调接口,而且也要注意回调成功后,我们可以选择编码给支付宝和微信发消息,让他不要再回调,其实也可以不做,
        //因为他的定时任务和我们的不一样是第三方平台的任务

        PaymentMsgExample paymentMsgExample = new PaymentMsgExample();
        paymentMsgExample.createCriteria().andStatusEqualTo(0);
        List<PaymentMsg> paymentMsgs = paymentMsgMapper.selectByExample(paymentMsgExample);
        if (paymentMsgs == null || paymentMsgs.size() == 0) {
            return;
        }
        for (PaymentMsg paymentMsg : paymentMsgs) {
            Integer orderId = paymentMsg.getOrderId();
            //请求处理订单的接口,可以通过httpClient
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            HttpPost httpPost = new HttpPost("http://localhost:8080/handleOrder");
            NameValuePair orderIdPair = new BasicNameValuePair("orderId", orderId + "");
            List<NameValuePair> list = new ArrayList<>();
            list.add(orderIdPair);
            HttpEntity httpEntity = new UrlEncodedFormEntity(list);
            httpPost.setEntity(httpEntity);

            CloseableHttpResponse response = httpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity());
            if ("success".equals(s)) {
                //如果发送成功
                paymentMsg.setStatus(1);
                paymentMsg.setUpdateTime(new Date());
                paymentMsg.setUpdateUser(0);
                paymentMsgMapper.updateByPrimaryKey(paymentMsg);
            } else {
                Integer failureCount = paymentMsg.getFailureCount();
                failureCount++;
                //这里要注意需要设置失败次数
                paymentMsg.setFailureCount(failureCount);
                if (failureCount > 5) {
                    paymentMsg.setStatus(2);
                }
                paymentMsg.setUpdateTime(new Date());
                paymentMsg.setUpdateUser(0);
                paymentMsgMapper.updateByPrimaryKey(paymentMsg);
            }
        }
    }
}